﻿using System;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using OrbitOne.CRM.CRMDiscovery;
using System.Net;

namespace OrbitOne.CRM
{
    internal class CRMTicketProvider
    {
        /// <summary>
        /// Get a ticket. Gets all the necessary data from the configuration file (CrmConfiguration section)
        /// </summary>
        /// <returns>a Ticket</returns>
        public static Ticket GetTicket()
        {
            var config = CrmConfiguration.Load();

            return GetTicket(config.Username, config.Password, config.Domain, config.Url, config.AuthenticationType, config.Instance);
        }

        public static Ticket GetTicket(string username, string password, string domain, string url, AuthenticationType auth)
        {
            return GetTicket(username, password, domain, url, auth, null);
        }

        public static Ticket GetTicket(string username, string password, string domain, string url, AuthenticationType auth, string instance)
        {
            var userid = domain + "\\" + username;
            var discoveryUrl = url + "/mscrmservices/2007/" + auth + "/CrmDiscoveryService.asmx";

            if (string.IsNullOrEmpty(instance))
            {
                var startIndex = url.IndexOf(':') + 3;
                var length = url.IndexOf('.') - startIndex;
                instance = url.Substring(startIndex, length);
            }

            var discoveryService = new CrmDiscoveryService
                                       {
                                           Url = discoveryUrl,
                                           Credentials = new NetworkCredential(username, password, domain)
                                       };

            var organisationRequest = new RetrieveOrganizationsRequest
                                          {
                                              UserId = userid,
                                              Password = password
                                          };

            //we don't care about no certificates!
            ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;

            var orgResponse = (RetrieveOrganizationsResponse)discoveryService.Execute(organisationRequest);

            OrganizationDetail organizationDetail = null;
            foreach (var detail in orgResponse.OrganizationDetails)
            {
                if (detail.OrganizationName.ToUpperInvariant().Equals(instance.ToUpperInvariant()))
                {
                    organizationDetail = detail;
                }
            }

            if (organizationDetail == null)
                throw new Exception("The specified organization was not found");

            var ticketRequest = new RetrieveCrmTicketRequest
            {
                OrganizationName = organizationDetail.OrganizationName,
                UserId = userid,
                Password = password
            };

            return new Ticket((
                (RetrieveCrmTicketResponse)discoveryService.Execute(ticketRequest)).CrmTicket,
                instance,
                url + "/mscrmservices/2007/CrmService.asmx",
                url + "/mscrmservices/2007/MetadataService.asmx",
                auth);
        }
    }
}
